Completed
Push — master ( d362a9...56faa4 )
by Mark
14s queued 11s
created

Table   A

Complexity

Total Complexity 42

Size/Duplication

Total Lines 203
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 153
dl 0
loc 203
rs 9.0399
c 0
b 0
f 0
wmc 42

20 Functions

Rating   Name   Duplication   Size   Complexity  
A find 0 15 4
A findCollectionComposedPrimaryKey 0 11 2
A addIndex 0 3 1
A removeIndex 0 3 1
A findCollection 0 9 2
A setupIndexes 0 3 1
B toComposedKey 0 16 6
A truncate 0 4 1
A setup 0 8 1
A registerIndex 0 3 1
A findOne 0 3 3
A insert 0 17 4
A make 0 3 1
A select 0 7 2
A all 0 10 2
A findOneComposedPrimaryKey 0 3 3
A getIndexByKey 0 3 1
A delete 0 9 2
A allModels 0 6 1
A update 0 17 3

How to fix   Complexity   

Complexity

Complex classes like Table often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
import {Model} from "./Model.js";
2
import Collection from "./Collection.js";
3
import Index from "./Table/Index";
4
import {TableInterface, ModelInterface, ModelStaticInterface} from "../JeloquentInterfaces";
5
6
/**
7
 *
8
 */
9
export default class Table implements TableInterface {
10
11
    name: string;
12
13
    private _index: Index;
14
15
    private _model: ModelInterface;
16
17
    private _models: Map<string|number, ModelInterface>;
18
19
    private _primaryKeyFieldNames: Array<string>;
20
21
    constructor (model: ModelStaticInterface) {
22
        this.setup(model.getInstance());
23
    }
24
25
    get ids():Array<string|number> {
26
        return [...this._models.keys()];
27
    }
28
29
    get indexes(): Map<string, Map<string|number, Set<string|number>>> {
30
        return this._index.indexes;
31
    }
32
33
    get models(): Map<string|number, ModelInterface> {
34
        return this._models;
35
    }
36
37
    static make(model: ModelStaticInterface): Table {
38
        return new Table(model);
39
    }
40
41
    public addIndex(indexName:string, lookUpKey:string, id:string|number): void {
42
        this._index.addValue(indexName, lookUpKey, id);
43
    }
44
45
    public all(): Collection {
46
        const values = [...this._models.values()];
47
        const numberOfValues = values.length;
48
        const collection = new Collection();
49
        for (let i = 0; i < numberOfValues; i += 10000) {
50
            collection.push(...values.slice(i, i + 10000));
51
        }
52
53
        return collection;
54
    }
55
56
    /**
57
     * @deprecated
58
     */
59
    public allModels(): Map<string | number, ModelInterface> {
60
        return this.models;
61
    }
62
63
    public delete(id:string|number): void {
64
        if (!this._models.has(id)) {
65
            throw new Error('Record doesn\'t exists');
66
        }
67
68
        this._index.removeValueByModel(this.findOne(id));
69
70
        this._models.delete(id);
71
    }
72
73
    public find(id:number|string|object|Array<string|number|object>): Collection|ModelInterface|null {
74
        const hasComposedPrimaryKey = this._primaryKeyFieldNames.length > 1;
75
        if (Array.isArray(id)) {
76
            if (hasComposedPrimaryKey) {
77
                return this.findCollectionComposedPrimaryKey(id as Array<object>);
78
            }
79
            return this.findCollection(id as Array<string|number>);
80
        }
81
82
        if (hasComposedPrimaryKey) {
83
            return this.findOneComposedPrimaryKey(id as object);
84
        }
85
86
        return this.findOne(id as (string|number));
87
    }
88
89
    public getIndexByKey(key: string): Map<string|number, Set<string|number>> {
90
        return this._index.getIndexByKey(key);
91
    }
92
93
    public insert(model: ModelInterface): void {
94
        if (this._models.has(model.primaryKey)) {
95
            throw new Error('Record already exists');
96
        }
97
98
        if (!(model instanceof Model)) {
99
            throw new Error('Record should be instance of model');
100
        }
101
102
        model.resetDirty();
103
104
        if (model.primaryKey != null) {
105
            this._models.set(model.primaryKey, model);
106
        }
107
108
        this._index.addValueByModel(model);
109
    }
110
111
    public registerIndex(indexName:string): void {
112
        this._index.register(indexName);
113
    }
114
115
    public removeIndex(indexName:string, lookUpKey:string, id:string|number): void {
116
        this._index.removeValue(indexName, lookUpKey, id)
117
    }
118
119
    public select(id:string|number): Collection|ModelInterface|null {
120
        if (!this._models.has(id)) {
121
            throw new Error('Record doesn\'t exists');
122
        }
123
124
        return this.find(id);
125
    }
126
127
    public setupIndexes(): void {
128
        this._model.tableSetup(this);
129
    }
130
131
    public truncate(): void {
132
        this._models.clear();
133
        this._index.truncate();
134
    }
135
136
    public update(model: ModelInterface): void {
137
        if (!this.models.has(model.primaryKey)) {
138
            throw new Error('Record doesn\'t exists');
139
        }
140
141
        if (!(model instanceof Model)) {
142
            throw new Error('Record should be instance of model');
143
        }
144
145
        this._index.removeValueByModel(model);
146
147
        model.resetDirty();
148
149
        this._index.addValueByModel(model);
150
151
        this._models.set(model.primaryKey, model);
152
    }
153
154
    private findCollection(id:Array<string|number>): Collection {
155
        const result = [];
156
        for (let i = 0; i < id.length; i++) {
157
            result.push(
158
                this._models.get(id[i])
159
            );
160
        }
161
        return new Collection(...result);
162
    }
163
164
    private findCollectionComposedPrimaryKey(id: Array<object>): Collection {
165
        const result = [];
166
        for (let i = 0; i < id.length; i++) {
167
            result.push(
168
                this._models.get(
169
                    this.toComposedKey(id[i])
170
                )
171
            );
172
        }
173
        return new Collection(...result);
174
    }
175
176
    private findOne(id: string|number): ModelInterface|null {
177
        return this._models.get(id) ?? null;
178
    }
179
180
    private findOneComposedPrimaryKey(id: object|string): ModelInterface|null {
181
        return this._models.get(this.toComposedKey(id)) ?? null;
182
    }
183
184
    private setup(model: ModelInterface) {
185
        this.name = model.className;
186
        this._primaryKeyFieldNames = model.primaryKeyName;
187
188
        this._model = model;
189
        this._models = new Map();
190
        this._index = new Index();
191
    }
192
193
    private toComposedKey(id:string|object): string|null {
194
        if (typeof id === 'string') {
195
            return id;
196
        }
197
198
        if (id === null) {
199
            return null;
200
        }
201
202
        const key = [];
203
        for (let i = 0; i < this._primaryKeyFieldNames.length; i++) {
204
            key.push(id[this._primaryKeyFieldNames[i]] ?? '');
205
        }
206
207
        return key.join('-');
208
    }
209
}